/* xeroskernel.h - disable, enable, halt, restore, isodd, min, max */

/* Symbolic constants used throughout Xinu */

typedef	char		Bool;		/* Boolean type			*/
#define	FALSE		0		/* Boolean constants		*/
#define	TRUE		1
#define	EMPTY		(-1)		/* an illegal gpq		*/
#define	NULL		0		/* Null pointer for linked lists*/
#define	NULLCH		'\0'		/* The null character		*/


/* Universal return constants */

#define	OK		 1		/* system call ok		*/
#define	SYSERR		-1		/* system call failed		*/
#define	EOF		-2		/* End-of-file (usu. from read)	*/
#define	TIMEOUT		-3		/* time out  (usu. recvtim)	*/
#define	INTRMSG		-4		/* keyboard "intr" key pressed	*/
					/*  (usu. defined as ^B)	*/
#define	BLOCKERR	-5		/* non-blocking op would block	*/

/* Functions defined by startup code */


void bzero(void *base, int cnt);
void bcopy(const void *src, void *dest, unsigned int n);
int kprintf(char * fmt, ...);
void lidt(void);
void init8259(void);
void disable(void);
void outb(unsigned int, unsigned char);
unsigned char inb(unsigned int);

extern void kmeminit(void);
extern void *kmalloc(int size);
extern void kfree(void *ptr);

#define MAX_PROC        64
#define SYSCALL_INT		80
#define TIMER_INT		32
#define KEYBOARD_INT	33
#define PROC_STACK      (4096 * 4)
#define MAX_DEV			2
#define MAX_FD			4

#define STATE_STOPPED   0
#define STATE_READY     1
#define STATE_SEND		2
#define STATE_RECV		3
#define STATE_BLOCKED 4
#define STATE_SLEEPING 5

#define SYS_STOP        0
#define SYS_YIELD       1
#define SYS_CREATE      2
#define SYS_TIMER       3
#define SYS_GET_PID		4
#define SYS_PUT			5
#define SYS_SEND		6
#define SYS_RECV		7
#define SYS_SLEEP		8
#define SYS_SIGHANDLER 	9
#define SYS_SIGNAL    	10
#define SYS_SIGWAIT 	11
#define SYS_SIGRETURN 	12
#define SYS_OPEN		13
#define SYS_CLOSE		14
#define SYS_WRITE		15
#define SYS_READ		16
#define SYS_IOCTL		17
#define SYS_KEYBOARD	18

#define CONSOLE 0
#define KEYBOARD 1

#define TIMESLICE 100        //The initPIT argument so 10ms 
#define MS 1000
#define MS_PER_SLICE 10      //(MS/TIMESLICE)

#define SIG_MAX 32

#define DEBUG 0
#define DEBUG2 0

#define STARTING_EFLAGS         0x00003200 //new requirement

typedef void    (*funcptr)(void);
typedef struct struct_pcb pcb;

typedef struct devsw{
	int dvnum;
	int (*dvopen)();
	int (*dvclose)();
	int (*dvread)();
	int (*dvwrite)();
	int (*dvioctl)();
	int (*dviint)();
	pcb *owner;
} devsw;

typedef struct fd_entry{
	devsw *device;
}fd_entry;

struct struct_pcb {
    long        esp;
    pcb         *next;
    int         state;
    unsigned int pid;
    int         ret;
    long        args;
    int 		sleepticks;
	unsigned int dest_pid;
	unsigned int *from_pid;
	void		*buffer;
	int			buffer_len;
	unsigned int free_addr;
	unsigned int validmask;
	unsigned int acceptedmask;
	unsigned int pendingmask;
	funcptr sigtable[SIG_MAX]; //sig table
	pcb *senderQ;
	fd_entry fd_table[MAX_FD];
};

extern pcb     proctab[MAX_PROC];
#pragma pack(1)

typedef struct context_frame {
  unsigned int        edi;
  unsigned int        esi;
  unsigned int        ebp;
  unsigned int        esp;
  unsigned int        ebx;
  unsigned int        edx;
  unsigned int        ecx;
  unsigned int        eax;
  unsigned int        iret_eip;
  unsigned int        iret_cs;
  unsigned int        eflags;
  unsigned int        stackSlots[4];
} context_frame;

struct devsw devtab[MAX_DEV];

extern unsigned short getCS(void);
extern void     kmeminit( void );
extern void     *kmalloc( int size );
extern void     dispatch( void );
extern void     dispatchinit( void );
extern void     ready( pcb *p );
extern void		proc_cleanup(pcb *p);
extern pcb      *next( void );
extern void     contextinit( void );
extern int      contextswitch( pcb *p );
extern void     set_evec(unsigned int xnum, unsigned long handler);

extern void     root( void );
extern void     root2( void );
extern void		testsyscalls(void);

void printCF (void * stack);

int syscall(int call, ...);
int syscreate(void (*func)(), int stack); 
int sysyield(void);
int sysstop(void);
extern unsigned int sysgetpid(void);
extern void sysputs(char *str);
extern int syssend(unsigned int dest_pid, void *buffer, int buffer_len);
extern int sysrecv(unsigned int *from_pid, void *buffer, int buffer_len);
int sysopen(int device_no);
int sysclose(int fd);
int syswrite(int fd, void *buff, int bufflen);
int sysread(int fd, void *buff, int bufflen);
int sysioctl(int fd, unsigned long command, ...);
extern int syssighandler(int signal, void (*newHandler)(void *), void (** oldHandler)(void *));
extern syskill(int pid, int signum);

extern int      create( funcptr fp, int stack );

//Sleeping
extern unsigned int syssleep(unsigned int milliseconds);		//for sys_sleep
extern void sleep(pcb *p, unsigned int milliseconds);			//sleep
extern void tick(void);
// extern void wakeup(pcb *p);

//IDLE process
extern void init_idle_proc( void );
pcb *idleproc;

extern int send(unsigned int dest_pid, void *buffer, int buffer_len, pcb *sender);
extern int recv(unsigned int *from_pid, void *buffer, int buffer_len, pcb *receiver);

extern pcb *getPCB(unsigned int id);
extern int getPCBi(unsigned int id);

//signals
int signal(int pid, int sig);
int sigwait(void);
void sigtramp(void (*handler)(void *), void *cntx, void *osp);
void sigreturn(void *old_sp);
int installHandler( pcb *p, int sig, void (*newHandler)(void *), void (** oldHandler)(void *) );
int findLargestBit( unsigned int bits );
Bool isLargestBit(pcb *p);

extern void init_device();
extern int di_open(pcb *p, int device_no);
extern int di_close(pcb *p, int fd);
extern int di_write(pcb *p, int fd, void *buff, int bufflen);
extern int di_read(pcb *p, int fd, void *buff, int bufflen);
extern int di_ioctl(pcb *p, int fd, unsigned long command, ...);

